package paper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import paper.extractor.*;
import statistics.Counter;
import statistics.ReferencesCounter;
import util.CommonUtil;
import util.FileUtil;

public class PubMedDB implements PapersDB, Counter {
	public static final String PUBMED_RESOURCE_URL = "http://www.ncbi.nlm.nih.gov/pubmed/";
	
	protected Counter domainRefStatistics; 
	
	public PubMedDB() {
		domainRefStatistics = new ReferencesCounter();
	}
	
	@Override
	public List<String> findLinksToPaper(String pubmedID) {
		List<String> links = new ArrayList<String>();
		Document doc;
		try {
			doc = Jsoup.connect(PUBMED_RESOURCE_URL+pubmedID).get();
			Elements allLinks = doc.select("a");
			for (Element l: allLinks) {
				String ref = l.attr("ref");
				if (ref!=null && ref.startsWith("PrId=")) {
					links.add(l.attr("href"));
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return links;
	}
	
	//takes pubmedID
	//return either null or BioMedCentralID 
	public String getBiomedCentralID(String documentID)
	{
		String bioMedID = null;
		List<String> links = findLinksToPaper(documentID);
		for (String link: links) {
			if (isTransitiveURL(link)) {
				link = CommonUtil.getDestinationOfTransitiveURL(link);
			}
			if(link.contains("biomedcentral.com"))
			{
				bioMedID = link.replace("http://www.biomedcentral.com/", "");
				bioMedID = bioMedID.replace("/", "-");
			}
		}
		return bioMedID;
	}
	
	@Override
	public boolean downloadPaper(String documentID, String downloadFolder) {
		List<String> links = findLinksToPaper(documentID);
		for (String link: links) {
			domainRefStatistics.incrementCounter(link);
		}
		for (String link: links) {
			if (isTransitiveURL(link)) {
				link = CommonUtil.getDestinationOfTransitiveURL(link);
			}
			LinkToPaperExtractor extractor = getResponibleLinkToPaperExtractor(link);
			if (extractor!=null) {
				String fileURL = extractor.extractLinkToPaper(link);
				if (fileURL!=null) {
					String fileName = CommonUtil.getFileNameWithExtension(fileURL);
					//String downloadPath = downloadFolder+"/"+documentID+"."+CommonUtil.getFileExtension(fileURL);  
					if(!FileUtil.pathExists(downloadFolder)) {
						FileUtil.createDirectory(downloadFolder);
					}
					String downloadPath = downloadFolder+"/"+fileName;
					boolean downloaded = FileUtil.downloadFile(fileURL, downloadPath);	
					if (downloaded) {
						return true;
					} else {
						/** Delete the empty folder **/
						FileUtil.deleteDirectory(downloadPath);
						System.out.println("An error occured during downloading the paper with ID="+documentID);
					}
				}
			}
		}
		return false;
	}
	
	private LinkToPaperExtractor getResponibleLinkToPaperExtractor(String URL) {
		if (URL.contains("ncbi.nlm.nih.gov/pmc")) {
			return new PMCExtractor(URL);
		}
		else if (URL.contains("biomedcentral.com")) {
			return new BiomedCentralExtractor(URL);
		}
		//else if (URL.contains("cell.com")) {
		//	return new CellExtractor(URL);
		//}
		//else if (URL.contains("sciencedirect.com")) {
		//	return new ScienceDirectExtractor(URL);
		//}
		return null;
	}
	
	/** Checks whether the link follows to a known transitive server  **/
	private static boolean isTransitiveURL(String URL) {
		if (URL==null) {
			return false;
		}
		if (URL.contains("linkinghub.elsevier.com")) {
			return true;
		}
		return false;
	}
	
	/** Delegation of Statistical functionality to the instance of ReferencesCounter **/
	
	@Override
	public void incrementCounter(String URL) {
		domainRefStatistics.incrementCounter(URL);
	}

	@Override
	public void resetCounter() {
		domainRefStatistics.resetCounter();
		
	}

	@Override
	public void printCounterStatistics(String folder, String fileName) {
		domainRefStatistics.printCounterStatistics(folder, fileName);
	}
	
	/**
	 * Main class is used for testing purposes
	 */
	public static void main(String[] args) {
		PubMedDB pubmed = new PubMedDB();
		String filesFolder = "files/";
		if(!FileUtil.pathExists(filesFolder)) {
			FileUtil.createDirectory(filesFolder);
		}
		
		/** Testing PMC paper extractor **/
		pubmed.downloadPaper("11410843", filesFolder);
		
		/** Testing BiomedCentral paper extractor **/
		//pubmed.downloadPaper("21269460", filesFolder);
		
		/** Testing Science Direct paper extractor **/
		//pubmed.downloadPaper("10051399", filesFolder);
		
		/** Testing Cell paper extractor **/
		//pubmed.downloadPaper("11410842", filesFolder);
	}

}
